# coding: utf-8
# Author: legend
# @Time： 2020/8/27 下午10:05
import logging
import re

import settings
from apps.log.models import OperationLog
from apps.log.operations import C_USER, C_SIGN_OUT
from apps.log.serializers.log_serializer import OperationLogSchema
from utils.messages.handler import BaseHandler
from utils.redis import Redis
from utils.time import get_current_time_by_microsecond
from websocket.messages import UserPingResponse

logger = logging.getLogger('app.running.log')

error = logging.getLogger('app.error.log')


class ServerTimeRequestHandler(BaseHandler):
    async def do(self, *args, **kwargs):
        return {
            'time': get_current_time_by_microsecond(),
            'result_code': self.response_serializer_class.ResultCode.NORMAL
        }


class UserPingRequestHandler(BaseHandler):
    group_name = settings.LOGIN_CHANNEL_GROUP_NAME

    async def do(self, *args, **kwargs):
        context = kwargs.get('context')
        self.channel_group_name = settings.LOGIN_CHANNEL_GROUP_NAME
        token = kwargs.get('token')
        async with Redis() as redis:
            redis_token = await redis.hgetall(
                settings.REDIS_LOGIN_TOKEN_KEY.format(token=token),
            )
            now = get_current_time_by_microsecond()
            if redis_token:
                return {
                    'result_code': UserPingResponse.ResultCode.NORMAL,
                    'time': now,
                }
            else:
                await redis.hdel(settings.REDIS_LOGIN_USER_KEY.format(user_id=redis_token.get('id')), token)
                ipv4 = context.scope.get('headers')[0][1].decode().split(':')[0]
                if self.check_ipv4(ipv4):
                    data = {
                        'username': context.user.username,
                        'ipv4': ipv4,
                        'op_type': C_SIGN_OUT,
                        'op_sort': C_USER,
                        'desc': '超时退出系统'
                    }
                else:
                    data = {
                        'username': context.user.username,
                        'op_type': C_SIGN_OUT,
                        'op_sort': C_USER,
                        'desc': '超时退出系统'
                    }
                serializer = OperationLogSchema()
                if not serializer.validate(data):
                    await OperationLog.create(**data)
                return {
                    'result_code': UserPingResponse.ResultCode.ERROR,
                    'time': now
                }

    def check_ipv4(self, ipv4):
        if re.match(r"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$",
                    ipv4):
            return True
        else:
            return False

# class UserPingResponseHandler(BaseHandler, AsyncJsonWebSocketConsumerExtension):
#
#     async def do(self, *args, **kwargs):
#         pass
#
#     async def another_login(self, *args, **kwargs):
#         #  检测到其它登录时自动退出登录
#         try:
#             if 'serializer' in kwargs.keys():
#                 content = kwargs.get('serializer')
#                 user_id = content.get('id')
#                 username = content.get('username')
#                 token = content.get('token')
#                 async with RedisConnection() as redis:
#                     client_host = await redis.hget(
#                         settings.REDIS_LOGIN_TOKEN_KEY.format(token=token),
#                         'client_host'
#                     )
#                     if client_host != content.get('client_host'):
#                         # 退出登录
#                         await self.channel_layer.group_discard(self.channel_group_name.format(username=username),
#                                                                self.channel_name)
#                         await redis.hdel(settings.REDIS_LOGIN_USER_KEY.format(user_id=user_id), token)
#                         await self.sign_out(*args, **kwargs)
#                         return {'result_code': UserPingResponse.ResultCode.ANTHER_LOGIN,
#                                 'msg_id': get_current_time_by_microsecond(),
#                                 'msg_type': UserPingResponse.Meta.MSG_TYPE,
#                                 'data': {
#                                     'msg': '用户在其它地方登录',
#                                     'ip': content.get('client_host')
#                                 }}
#         except AttributeError as e:
#             error.exception(e)
#
#     async def sign_out(self, *args, **kwargs):
#         """
#         单点登录控制
#         :return:
#         """
#         content = kwargs.get('serializer')
#         key = settings.REDIS_LOGIN_USER_KEY.format(user_id=content.get('id'))
#         # 删除token
#         await (await self.redis()).hdel(key, content.get('token'))
#         await (await self.redis()).delete(settings.REDIS_LOGIN_TOKEN_KEY.format(token=content.get('token')))
